package com.td.library;

import com.td.library.config.FileType;
import com.td.library.utils.DeviceUtils;
import com.td.library.utils.FileUtils;
import com.td.library.utils.LogUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilityPackage;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.data.distributed.common.KvManagerConfig;
import ohos.data.distributed.common.KvManagerFactory;
import ohos.data.resultset.ResultSet;
import ohos.media.photokit.metadata.AVStorage;
import ohos.utils.net.Uri;

import java.io.*;
import java.util.Arrays;
import java.util.Optional;

/**
 * 分布式文件管理
 */
public class DistributedFileManager {
    private static final String TAG = DistributedFileManager.class.getSimpleName();

    private static final DistributedFileManager INSTANCE = new DistributedFileManager();

    // 缓存大小8M
    private static final int CACHE_SIZE = 8 * 1024;

    // 结束下标
    private static final int END_OF_FILE = -1;

    private Context mContext;
    private String mDistributedDirPath;
    private boolean diffDeviceName;


    /**
     * 获取管理类实例
     *
     * @return 管理类实例
     */
    public static DistributedFileManager getInstance() {
        return INSTANCE;
    }

    /**
     * 初始化管理类
     *
     * @param ability 页面ability
     * @param abilityPackage 应用abilityPackage
     */
    public void startUp(Ability  ability, AbilityPackage abilityPackage) {
        if (ability == null) {
            throw new NullPointerException("ability is nulll");
        }
        if (abilityPackage == null) {
            throw new NullPointerException("abilityPackage is nulll");
        }
        mContext = abilityPackage;
        mDistributedDirPath = ability.getDistributedDir().getPath();
        LogUtil.info(TAG, " mDistributedDir " + mDistributedDirPath);
        LogUtil.info(TAG, " mDistributedDir " + ability.getDistributedDir().getAbsolutePath());
    }

    /**
     * 将图片文件拷贝到分布式文件目录
     */
    public void copyCommonImageFiles() {
        // 图片外部存储URI
        copyFiles(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI);
    }

    /**
     * 将音频文件拷贝到分布式文件目录
     */
    public void copyCommonAudioFiles() {
        // 音频外部存储URI
        copyFiles(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI);
    }

    /**
     * 将视频文件拷贝到分布式文件目录
     */
    public void copyCommonVideoFiles() {
        // 视频外部存储URI
        copyFiles(AVStorage.Video.Media.EXTERNAL_DATA_ABILITY_URI);
    }

    /**
     * 将下载目录文件拷贝到分布式文件目录
     */
    public void copyCommonDownloadsFiles() {
        // 下载
        copyFiles(AVStorage.Downloads.EXTERNAL_DATA_ABILITY_URI);
    }

    /**
     * 拷贝系统文件，包括图片音频视频
     */
    public void copyCommonFiles() {
        LogUtil.debug(TAG, "copyCommonFiles begin");
        long beginTime = System.currentTimeMillis();
        copyCommonImageFiles();
        copyCommonAudioFiles();
        copyCommonVideoFiles();
        copyCommonDownloadsFiles();
        LogUtil.debug(TAG, "copyCommonFiles end, cost time " + (System.currentTimeMillis() - beginTime));
    }

    /**
     * 获取分布式文件路径
     *
     * @return 分布式文件路径
     */
    public String getDistributedDirPath() {
        return mDistributedDirPath;
    }

    /**
     * 获取分布式文件
     *
     * @return 分布式文件
     */
    public File getDistributedDirFile() {
        return new File(mDistributedDirPath);
    }

    private void copyFiles(Uri uri) {
        // 数据操作的辅助类
        DataAbilityHelper helper = DataAbilityHelper.creator(mContext);

        // 定义分布式显示字段
        String[] projections = new String[]{
                AVStorage.AVBaseColumns.ID,
                AVStorage.AVBaseColumns.DISPLAY_NAME,
                AVStorage.AVBaseColumns.DATA
        };

        try {
            // 根据uri查询出指定字段数据
            ResultSet resultSet = helper.query(uri, projections, null);
            if (resultSet == null) {
                LogUtil.info(TAG, "query result is empty");
                return;
            }

            // 读取结果集数据出来
            while (resultSet.goToNextRow()) {
                int mediaId = resultSet.getInt(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.ID));
                // 文件路径
                String filePath = resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DATA));
                // 从文件路径获取文件名
                String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
                // 追加媒体Id到Uri
                Uri tmpUri = Uri.appendEncodedPathToUri(uri, mediaId + "");
                // 写文件到分布式目录下
                writeToDistributedDir(mContext, helper, fileName, tmpUri);
            }

        } catch (DataAbilityRemoteException e) {
            LogUtil.error(TAG, "query file error");
        }
    }

    /**
     * 写文件到分布式目录下
     *
     * @param context 上下文
     * @param helper 帮助类
     * @param fileName 文件名
     * @param tmpUri 文件uri
     */
    private void writeToDistributedDir(Context context, DataAbilityHelper helper, String fileName, Uri tmpUri) {
        String suffix = FileUtils.getFileSuffix(fileName);

        // 本地设备名称
        String deviceId = DeviceUtils.getLocalDeviceInfo(context).getId();

        Optional<FileType> fileTypeOptional = Arrays.stream(FileType.values())
                .filter(fileType -> {
                    return !fileType.equals(FileType.FILE)
                            && !fileType.equals(FileType.OTHER)
                            && Arrays.asList(fileType.getFileSuffix()).contains(suffix);
                }).findFirst();

        FileType fileType = fileTypeOptional.orElse(FileType.OTHER);
        String parentFilePath = mDistributedDirPath
                + File.separator + deviceId
                + File.separator + fileType.getFileDirectoryName();
        File file = new File(parentFilePath);
        if (!file.exists()) {
            if (!file.mkdirs()) {
                return;
            }
        }

        String distributedFilePath = parentFilePath + File.separator + fileName;
        LogUtil.info(TAG, "distributedFilePath " + distributedFilePath);

        writeFile(distributedFilePath, helper, tmpUri);
    }

    private void writeFile(String distributedFilePath, DataAbilityHelper helper, Uri tmpUri) {
        File file = new File(distributedFilePath);
        if (file.exists()) {
            LogUtil.info(TAG, "distributedFilePath " + distributedFilePath + " exists");
            return;
        }

        FileDescriptor fileDescriptor = null;
        try {
            fileDescriptor = helper.openFile(tmpUri, "r");
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (fileDescriptor == null) {
            LogUtil.error(TAG, "distributedFilePath " + distributedFilePath + " exists");
        }
        try (InputStream inputStream = new FileInputStream(fileDescriptor);
            OutputStream outputStream = new FileOutputStream(file)) {
            FileUtils.copyFile(inputStream, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
